package com.healthcloud.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.healthcloud.entity.ExamTestProjectKindConclusion;
import com.healthcloud.entity.Patient;
import com.healthcloud.entity.PhysicalExam;
import com.healthcloud.entity.TestProjectItem;
import com.healthcloud.entity.TestProjectKind;
import com.healthcloud.entity.TestResult;
import com.healthcloud.service.ExamTestProjectKindConclusionService;
import com.healthcloud.service.HealthExamService;
import com.healthcloud.service.HealthReportService;
import com.healthcloud.service.IdentCorporeityResultService;
import com.healthcloud.service.PatientService;
import com.healthcloud.utils.DateUtils;
import com.healthcloud.utils.ApiRes;
import com.healthcloud.vo.IdentCorporeityVo;
import com.healthcloud.vo.PhysicalExamVo;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import springfox.documentation.annotations.ApiIgnore;

/**
 * 健康体检报告rest服务控制器 
 * Created by xiam on 2015/6/22. 
 * Updated by ZhengL on
 * 2015/07/24.
 */
@ApiIgnore
@Api(value = "示例说明", description = "健康体检报告rest服务控制器 ")
@Controller
@RequestMapping("/app")
public class HealthReportApiController {

	private String[] search = { "op", "username", "usertype", "token",
			"timestamp", "v", "appid", "sign", "testId", "idCard",
			"mkExamCode", "mkMedicalinstrumenId", "testDate" };

	private String[] tableList = { "基本信息", "血压", "血糖", "血脂", "血氧", "心电分析", "尿液" };
	private String[] table1 = { "身高", "体重", "腰臀比", "BMI", "结论" };
	private String[] table1_fcode = { "item_101006", "item_101007", "item_101003", "item_102006", "result_101" };
	private String[] table2 = { "收缩压", "舒张压", "周期脉搏", "结论" };
	private String[] table2_fcode = { "item_104001", "item_104002", "item_104003", "result_104" };
	private String[] table3 = { "餐后血糖", "空腹血糖", "结论" };
	private String[] table3_fcode = { "item_105002", "item_105001", "result_105" };
	private String[] table4 = { "总胆固醇", "高密度脂蛋白", "甘油三酯", "低密度脂蛋白", "尿酸", "结论" };
	private String[] table4_fcode = { "item_106001", "item_106002", "item_106004", "item_106003", "item_106005",
			"result_106" };
	private String[] table5 = { "血氧饱和度", "脉率", "结论" };
	private String[] table5_fcode = { "item_108001", "item_108002", "result_108" };
	private String[] table6 = { "心率", "P时限", "PR时限", "QRS时限", "QR时限", "QTc时限",
			"RV5振幅", "RV6振幅", "SV1振幅", "SV2振幅", "结论" };
	private String[] table6_fcode = { "item_103001", "", "", "", "", "", "", "", "", "",
			"result_103" };
	private String[] table7 = { "亚硝酸盐", "白细胞", "尿胆原", "尿蛋白", "隐血", "尿酮体",
			"胆红素", "尿糖", "维生素C", "PH","尿比重","结论" };
	private String[] table7_fcode = { "item_107002", "item_107001", "item_107003", "item_107004", "item_107006", "item_107008",
			"item_107009", "item_107010", "item_107011", "item_107005","item_107007","result_107" };

	@Autowired
	private HealthExamService healthExamService;
	@Autowired
	private HealthReportService healthReportService;
	@Autowired
	private PatientService patientService;
	@Autowired
	private IdentCorporeityResultService identCorporeityResultService;
	@Autowired
	private ExamTestProjectKindConclusionService examTestProjectKindConclusionService;
	@Autowired
	private Mapper beanMapper;

	//移动端获取体检报告jpg
	@ApiOperation(value = "移动端获取体检报告jpg",notes ="移动端获取体检报告jpg")
	@ResponseBody
	@RequestMapping(value = "/HealthReport/get")
	public Object findReport(HttpServletRequest request) {
		List<Map<String, String>> mapList = new ArrayList<Map<String, String>>();
		ApiRes jm = new ApiRes(mapList);
		try {/*
			Map<String, String> dataMap = getDataMap(request, search);
			jm = verify(dataMap, jm);
			 String separator = File.separator;// 分隔符（防止linux分隔符不同报错）
			 String contextPath = request.getContextPath(); // 项目相对路径
			 String realPath = request.getSession().getServletContext()
			 .getRealPath(separator); // 项目绝对路径
			 String basePath = request.getScheme() + ":"+separator+separator
			 + request.getServerName() + ":" + request.getServerPort()
			 + contextPath + separator;// 服务器访问路径
			 String fileDir = "assets" + separator + "report" +
			 separator;//服务器资源文件夹
			Map<String, String> m = new HashMap<String, String>();
			if (!jm.isSuccess()) {

			} else {
				String idCard = dataMap.get("idCard");
				String mkCode = dataMap.get("mkExamCode");
				if (StringUtils.isBlank(mkCode)) {// 以前版本的接口使用testId字段作为体检编号
					mkCode = dataMap.get("testId");
				}
				PhysicalExamVo v = showDetailExam(mkCode, idCard,request);
				if (StringUtils.isNotBlank(idCard)
						&& StringUtils.isNotBlank(mkCode)) {
					String filePath = fileDir + idCard + separator; // 患者个人文件夹（以身份证号命名）
					String pdf_file_path = realPath + filePath + mkCode
							+ ".pdf";
					String pdf_analysis_path = realPath + filePath + mkCode
							+ "_analysis.pdf";
					String pdf_final_path = realPath + filePath + mkCode
							+ "_final.pdf";
					File file = new File(realPath + filePath);
					boolean flag = false;
					if (!file.exists() && !file.isDirectory()) {
						file.mkdir();
						// 生成pdf
						flag = createReport(realPath+fileDir,pdf_file_path, pdf_analysis_path,
								pdf_final_path, v);
						// 生成jpg
						if (flag) {
							m = pdf2Jpg(pdf_final_path, basePath + filePath,
									realPath + filePath, mkCode, 2);
						} else {
							m = pdf2Jpg(pdf_file_path, basePath + filePath,
									realPath + filePath, mkCode, 2);
						}
						mapList.add(m);
					} else {
						File file_pdf = new File(pdf_file_path);
						if (file_pdf.exists()) {
							// 生成图片
							m = pdf2Jpg(pdf_file_path, basePath + filePath,
									realPath + filePath, mkCode, 2);
							mapList.add(m);
						} else {
							// 生成pdf
							flag = createReport(realPath+fileDir,pdf_file_path,
									pdf_analysis_path, pdf_final_path, v);
							// 生成jpg
							if (flag) {
								m = pdf2Jpg(pdf_final_path,
										basePath + filePath, realPath
												+ filePath, mkCode, 2);
							} else {
								m = pdf2Jpg(pdf_file_path, basePath + filePath,
										realPath + filePath, mkCode, 2);
							}
							mapList.add(m);
						}
					}
				}
				jm.setData(mapList);
				jm.setSuccess(true);
			}
		*/} catch (Exception e) {
			e.printStackTrace();
		}
		return jm;
	}

	// 页面载入pdf
	@RequestMapping(value = "/HealthReport/createReport")
	private String showPdf(HttpServletRequest request, String mkCode,
			String idCard,String pMenuId, Model model) {
		try {
			 String separator = File.separator;// 分隔符（防止linux分隔符不同报错）
			 String contextPath = request.getContextPath(); // 项目相对路径
			 String realPath = request.getSession().getServletContext()
			 .getRealPath(separator); // 项目绝对路径
			 String basePath = request.getScheme() + ":"+separator+separator
			 + request.getServerName() + ":" + request.getServerPort()
			 + contextPath + separator;// 服务器访问路径
			 String fileDir = "assets"+separator+"report"+separator;
			 //服务器资源文件夹
			String filePath = fileDir + idCard + separator; // 患者个人文件夹（以身份证号命名）
			String fileName = mkCode + ".pdf";
			String fileName2 = mkCode + "_analysis.pdf";
			String fileFinal = mkCode + "_final.pdf";
			PhysicalExamVo v = showDetailExam(mkCode, idCard,request);
			File file = new File(realPath + filePath);
			if (!file.exists() && !file.isDirectory()) {
				file.mkdir();
			}
			File pdfFile = new File(realPath + filePath + fileFinal);
			boolean flg = false;
			if (pdfFile.exists()) {

			} else {
				flg = createReport(realPath+fileDir,realPath + filePath + fileName, realPath
						+ filePath + fileName2,
						realPath + filePath + fileFinal, v);
			}
			String visitPath = "";
			if(flg){
				visitPath = basePath + filePath + fileFinal;
			}else{
				visitPath = basePath + filePath + fileName;
			}
			model.addAttribute("filePath", visitPath);
			model.addAttribute("resultData", v);
			model.addAttribute("pMenuId", pMenuId);
			// Map m = pdf2Jpg(realPath+filePath +
			// fileName,basePath+filePath,realPath+filePath,mkCode,1f);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "healthExam/showReport";
	}

	/**
	 * 将指定pdf文件的首页转换为指定路径的缩略图
	 *
	 * @param pdfPath
	 *            原文件路径，例如d:/test.pdf
	 * @param imagepath
	 *            生成图片放置的文件夹，例如 d:/test/
	 * @param imageName
	 *            图片文件名称 （不带后缀） 例如 test
	 * @param basePath
	 *            服务器访问路径
	 * @param zoom
	 *            缩略图显示倍数，1表示不缩放，0.3则缩小到30%
	 */
	/*private Map<String, String> pdf2Jpg(String pdfPath, String basePath,
			String imagepath, String imageName, float zoom)
			throws PDFException, PDFSecurityException, IOException {
		Map<String, String> m = new HashMap<String, String>();
		String FILETYPE_JPG = "jpg";
		String SUFF_IMAGE = "." + FILETYPE_JPG;
		Document document = null;
		float rotation = 0f;
		document = new Document();
		document.setFile(pdfPath);
		int maxPages = document.getPageTree().getNumberOfPages();
		for (int i = 0; i < maxPages; i++) {
			BufferedImage img = (BufferedImage) document.getPageImage(i,
					GraphicsRenderingHints.SCREEN, Page.BOUNDARY_CROPBOX,
					rotation, zoom);
			Iterator iter = ImageIO.getImageWritersBySuffix(FILETYPE_JPG);
			ImageWriter writer = (ImageWriter) iter.next();
			String fileName = imageName + "(" + i + ")" + SUFF_IMAGE;
			String filePath = imagepath + fileName;
			String visitPath = basePath + fileName;
			File outFile = new File(filePath);
			FileOutputStream out = new FileOutputStream(outFile);
			ImageOutputStream outImage = ImageIO.createImageOutputStream(out);
			writer.setOutput(outImage);
			writer.write(new IIOImage(img, null, null));
			m.put("url" + i, visitPath);
		}
		return m;
	}*/

	/**
	 * 创建PDF
	 * @param assetsPath
	 *            项目资源文件夹
	 * @param filePath
	 *            体检报告路径
	 * @param filePath2
	 *            体质报告路径
	 * @param target
	 *            最终合并后报告路径
	 * @param v
	 *            参数信息
	 * @return true:最终报告生成成功；false：最终报告生成失败(体检报告或者体质报告不存在)
	 */
	private boolean createReport(String assetsPath,String filePath, String filePath2,
			String target, PhysicalExamVo v) {
		boolean flag = false;
		try {
			HashMap<String, String[]> tableMap = new HashMap<String, String[]>();
			tableMap = makeTable();
			File file1 = new File(filePath);
			File file2 = new File(filePath2);
			if(!file1.exists()){
				healthReportService.createPDF(v, filePath, tableMap);
			}
			if(!file2.exists()){
				createAnalysisPdf(assetsPath,assetsPath+v.getIdCard()+File.separator, v.getIdCard(), v.getMkExamCode());
			}
			flag = mergePDF(filePath, filePath2, target);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * 查找体检详细数据用于形成体检报告
	 * @param mkCode 体检编号
	 * @param idCard 身份证好
	 * @return 
	 * @throws Exception
	 */
	private PhysicalExamVo showDetailExam(String mkCode, String idCard,HttpServletRequest request)
			throws Exception {
		PhysicalExam pe = healthExamService
				.findByExamIdAndIdNum(mkCode, idCard);
		PhysicalExamVo vo = new PhysicalExamVo();
		if (pe != null) {
			beanMapper.map(pe, vo);
			Patient pt = patientService.findByIdCard(idCard);
			if (pt != null) {
				vo.setPatientName(pt.getRealname());
				vo.setMedicalCardNum(pt.getMedicalCardNum());
				vo.setHomeAddress(pt.getHomeAddress());
				vo.setPhone(pt.getPhone());
				Date dt = pt.getBirthday();
				Integer ge = pt.getGender();
				if (dt != null) {
					String age = DateUtils.getAge(dt);
					vo.setAge(age);
				}
				if (ge == 2) {
					vo.setSex("女");
				} else if(ge == 1){
					vo.setSex("男");
				}else{
					vo.setSex("不详");
				}
				String imageCode = pt.getUserImage();
				String imageDir = healthExamService.faceImage(pt.getIdCard(),imageCode,request);
				vo.setUserImage(imageDir);
			}
			TestResult entity = new TestResult();
			entity.setFromId(mkCode);
			entity.setIdCard(idCard);
			List<TestResult> templist = healthExamService.findByEntity(entity);
			ExamTestProjectKindConclusion entity2 = new ExamTestProjectKindConclusion();
			entity2.setMkExamCode(mkCode);
			//查询健康体检项目小结
			List<ExamTestProjectKindConclusion> tempList2 = examTestProjectKindConclusionService.findByEntity(entity2); 
			Map<String, String> m = new HashMap<String, String>();
			if (templist != null && templist.size() > 0) {
				for (TestResult te : templist) {
					String itemCode = te.getTestItemCode();
					TestProjectItem item = healthExamService
							.selectItem(itemCode);
					String value = te.getTestValue();
					String report = te.getTestReport();
					String result = te.getTestResult();
					if (item != null) {// 必须存在item的fastCode，才会记录数据
						String code = item.getTestItemCode();
						if (StringUtils.isNotBlank(code)) {
							if (!m.containsKey("item_"+code)) {
								m.put("item_"+code, value);
							}
							if (!m.containsKey("item_"+code + "_report")) {//健康体检单项结论
								m.put("item_"+code + "_report", report);
							}
							if (!m.containsKey("item_"+code + "_result")) {//单项结果（0正常 1偏高 -1偏低）
								m.put("item_"+code + "_result", result);
							}
						} else {
							continue;
						}
					} else {
						continue;
					}
				}
			}
			if(tempList2!=null&&tempList2.size()>0){//健康体检项目小结
				for (ExamTestProjectKindConclusion con : tempList2) {
					String kindId = con.getTestKindCode();
					TestProjectKind tk = healthExamService.selectKind(kindId);
					if(tk!=null){
						String kindCode = tk.getTestKindCode();
						String key = "result_"+kindCode;
						m.put(key, con.getConclusion());
					}
				}
			}
			Date dt = pe.getExamDate(); //体检时间
			if (dt == null) {
				dt = new Date();
			}
			String time = DateUtils.format(DateUtils.Date2Calendar(dt),"yyyy-MM-dd HH:mm:ss");
			vo.setExamDateStr(time);
			vo.setResultMap(m);
		}
		return vo;
	}

	/**
	 * 创建体质分析报告
	 * @param assetsPath
	 *            项目资源文件夹
	 * @param filePath
	 *            个人文件夹路径
	 * @param idCard
	 *            身份证号
	 * @param mkCode
	 *            体检编号
	 * @throws Exception
	 */
	private void createAnalysisPdf(String assetsPath,String filePath, String idCard, String mkCode)
			throws Exception {
		IdentCorporeityVo vo = identCorporeityResultService.findVo(idCard,
				mkCode);
		String chartImg = filePath + mkCode + "_analysis.jpg"; // 柱状分析图路径
		identCorporeityResultService.createChart(chartImg, vo);
		File image = new File(chartImg);
		if(image.exists()){
			String chartPdfTemp = filePath + mkCode + "_analysis_temp.pdf";// 临时pdf
			identCorporeityResultService.createPdf(chartPdfTemp, chartImg, vo);
			String analysisPdf = filePath + mkCode + "_analysis.pdf";// 体制报告pdf
			String backgroundImag = assetsPath + "background.png"; // 背景图路径
			identCorporeityResultService.createBackground(chartPdfTemp,
					analysisPdf, backgroundImag);
		}
	}

	/**
	 * 合并体检报告和体质报告
	 * 
	 * @param source1
	 *            体检报告pdf路径
	 * @param source2
	 *            体质报告pdf路径
	 * @param target
	 *            最终报告pdf路径
	 * @return true:最终报告生成成功；false：最终报告生成失败(体检报告或者体质报告不存在)
	 * @throws Exception
	 */
	private boolean mergePDF(String source1, String source2, String target)
			throws Exception {
		File file1 = new File(source1);
		File file2 = new File(source2);
		File fileT = new File(target);
		if (!fileT.exists()) {
			if (file1.exists() && file2.exists()) {
				PdfReader reader1 = new PdfReader(source1);
				PdfReader reader2 = new PdfReader(source2);
				FileOutputStream out = new FileOutputStream(target);
				com.itextpdf.text.Document document = new com.itextpdf.text.Document();
				PdfWriter writer = PdfWriter.getInstance(document, out);
				document.open();
				PdfContentByte cb = writer.getDirectContent();
//				int totalPages = 0;
//				totalPages += reader1.getNumberOfPages();
//				totalPages += reader2.getNumberOfPages();

				java.util.List<PdfReader> readers = new ArrayList<PdfReader>();
				readers.add(reader1);
				readers.add(reader2);

				int pageOfCurrentReaderPDF = 0;
				Iterator<PdfReader> iteratorPDFReader = readers.iterator();

				// Loop through the PDF files and add to the output.
				while (iteratorPDFReader.hasNext()) {
					PdfReader pdfReader = iteratorPDFReader.next();

					// Create a new page in the target for each source page.
					while (pageOfCurrentReaderPDF < pdfReader
							.getNumberOfPages()) {
						document.newPage();
						pageOfCurrentReaderPDF++;
						PdfImportedPage page = writer.getImportedPage(
								pdfReader, pageOfCurrentReaderPDF);
						cb.addTemplate(page, 0, 0);
					}
					pageOfCurrentReaderPDF = 0;
				}
				out.flush();
				document.close();
				out.close();
				return true;
			} else {
				return false;
			}
		} else {
			return true;
		}

	}

	// 获取请求中的参数
	private Map<String, String> getDataMap(HttpServletRequest request,
			String[] strs) {
		Map<String, String> dataMap = new HashMap<String, String>();
		Map<String, String[]> params = request.getParameterMap();
		for(int i=0;i<strs.length;i++){
			String key = strs[i].trim().toString();
			if (params.containsKey(key)) {
				String[] values = params.get(key);
				dataMap.put(key, values[0].toString());
			}
		}
		return dataMap;
	}

	// 构建pdf表格列名称和对应取值code
	private HashMap<String, String[]> makeTable() {
		HashMap<String, String[]> tableMap = new HashMap<String, String[]>();
		tableMap.put("tableList", tableList);
		tableMap.put("table1", table1);
		tableMap.put("table1_fcode", table1_fcode);
		tableMap.put("table2", table2);
		tableMap.put("table2_fcode", table2_fcode);
		tableMap.put("table3", table3);
		tableMap.put("table3_fcode", table3_fcode);
		tableMap.put("table4", table4);
		tableMap.put("table4_fcode", table4_fcode);
		tableMap.put("table5", table5);
		tableMap.put("table5_fcode", table5_fcode);
		tableMap.put("table6", table6);
		tableMap.put("table6_fcode", table6_fcode);
		tableMap.put("table7", table7);
		tableMap.put("table7_fcode", table7_fcode);
		return tableMap;
	}

	// 验证方法
	private ApiRes verify(Map<String, String> jsonMap, ApiRes msg) {
//		String username = jsonMap.get("username");
//		String usertype = jsonMap.get("usertype");
//		String token = jsonMap.get("token");
//		String timestamp = jsonMap.get("timestamp");
//		String v = jsonMap.get("v");
//		String appid = jsonMap.get("appid");
//		String sign = jsonMap.get("sign");
//		 if(StringUtil.isBlank(token)){
//		 msg.setSuccess(false);
//		 msg.setError("missing_token");
//		 }else{
//		 OauthSubjectWrapper wrapper = cache.get(token);
//		 if (wrapper == null) {
//		 msg.setSuccess(false);
//		 msg.setError("invalid_token");
//		 }
//		 }
		msg.setSuccess(true);
		return msg;
	}

}
